<template>
    <div>
        <div class="flex">
            <Upload
                :show-upload-list='false'
                :on-success="getFileUrl"
                :headers="uploadHeader"
                :on-progress="getProgress" 
                ref='uploadFile' 
                :action="uploadAction" 
                :before-upload="handleUploadIcon">
                <Button icon="ios-cloud-upload-outline" :disabled="loading || disabled">上传{{fileTypeName}}</Button>
            </Upload>
            <WarningTip style="margin-left:3px;">
                <slot name="tooltip"></slot>
                <p style="white-space: normal;word-break: break-all;" v-if="format && format.length > 0">支持上传类型:{{format && format.toString()}}</p>
                <p style="white-space: normal;"> 
                    文件名称:不能包含下列任意英文字符 \ / : * ? " < > |，长度为1-64个字符
                </p>
            </WarningTip>
        </div>
        <div v-if="uploadFile.name && loading">
            <div v-if="showUploadInfo" class="flex">
                <span class="mr5 mw30 text-ellipsis" :title="uploadFile.name">文件名: {{ uploadFile.name}}</span>
                <span class="mr5 mw30 text-ellipsis">文件大小：{{ size }}</span>
                <span class="mw30 text-ellipsis">上传速度：{{ speed }}</span>
            </div>
            <Progress v-if="showUploadProgress" :percent="progress" hideInfo :stroke-width="5" style="line-height: 1;"></Progress>
        </div>
        <div class="file-list" v-if="(uploadFile.filePath || uploadFile.name) && !loading">
            <template v-if="fileType === 'images'">
                <img :src="`/Learn${uploadFile.filePath}`"
                    style="width:auto;height:40px;vertical-align: middle;"/>
                <Button type="text" icon="ios-trash" @click="removeFile"></Button>
            </template>
            <template v-else-if="fileType === 'glb'">
                <span class="file-name">{{uploadFile.name || uploadFile.filePath}}</span>
                <Button type="text" icon="ios-trash" @click="removeFile"></Button>
            </template>
            <template v-else>
                <div>
                    <Icon :type="fileType === 'docs' ? 'ios-document' : fileType === 'videos' ? 'ios-videocam' : 'logo-dropbox'" :size="16"/>
                    <span class="file-name">{{uploadFile.name}}</span>
                </div>
                <Button type="text" icon="ios-trash" @click="removeFile"></Button>
            </template>
        </div>
</div>
</template>
  
<script>
  export default {
      props: {
          value:{ //v-model
            type: Object,
            default:() => {
                return {
                    fileId: '',
                    filePath: '',
                    fileName: ''
                }
            }
          },
          filePath:{ //.sync
            type: String,
            default: ''
          },
          fileName:{ //.sync
            type: String,
            default: ''
          },
          fileId:{ //.sync
            type: String,
            default: ''
          },
          fileSize:{ //.sync
            type: Number,
            default: 0
          },
          format: {
              type: Array,
              default: () => []
          },
          showUploadProgress:{ //是否显示上传进度
              type: Boolean,
              default: true
          },
          showUploadInfo:{ //是否显示上传信息
              type: Boolean,
              default: true
          },
          bucket:{ //桶
              type: String,
              default: ''
          },
          type:{
            type: String,
            default: '',
            validator:function(val){//设置自定义验证规则
                return !val || (val && ['images','docs','videos','audios','glb','files'].includes(val))
            }
          },
          disabled:{ //是否显示上传信息
              type: Boolean,
              default: false
          },
          btnTxt:{
            type: String,
            default: ''
          }
      },
      data() {
          return {
              visibility:'company',
              uploadHeader: {
                  Authorization: localStorage.token,
                  Accept: '*/*'
              },
              speed: 0,
              loaded: 0,
              progress: 0,
              size:0,
              fileType:this.type || '',
              loading:false,
              uploadAction:'',
              uploadFile:this.value, //当前上传文件信息
              imagesArr:["jpeg","jpg","jpe","png","gif","tiff","bmp","dwg","psd","ico","rgb","ogx","pcx","mdi","tif","pgm","cmx","webp"],
              docsArr: ["pdf","doc","docx","xls","xlsx","xla","pptx","pps","ppt","rtf","txt","md"],
              filesArr:["zip","bz2","7z","cab","rar","epub"],
              videosArr:["mp4","webm","ogv","ogg","3gp","3g2","m4v","mpg","vob","fli","mkv","asf","asx","wmv","flv","avi"],
              audiosArr:["m4a","sil","ra","ram","au","wma","aiff","mp3","mid","midi","rmi","oga","wav","caf","flac","adp","aac"],
              glbArr:['glb']
            }
      },
      computed: {
        fileTypeName() {
            if(this.btnTxt){
                return this.btnTxt
            }else{
                if(this.fileType){
                    switch(this.fileType) {
                        case 'docs': return '文档'
                        case 'videos': return '视频'
                        case 'audios': return '音频'
                        case 'images': return '图片'
                        case 'glb': return '图片'
                    }
                }
            }
        },
      },
      watch: {
          loading(val){ //外层modal的确定按钮可能需要控制
              this.$emit('update:uploadLoading',val)
          },
          filePath(val){
            if(!val){
                this.uploadFile = {};
            }else if(val && val !== this.uploadFile.filePath){
                this.uploadFile.filePath = val;
            }
          },
          fileId(val){
            if(!val){
                this.uploadFile = {};
            }else if(val && val !== this.uploadFile.fileId){
                this.uploadFile.fileId = val;
            }
          },
          fileName(val){
            if(!val){
                this.uploadFile = {};
            }else if(val && val !== this.uploadFile.name){
                this.uploadFile.name = val;
            }
          }
      },
      mounted() {
        if(!this.$props.value){
            this.uploadFile = {
                fileId:this.fileId,
                name:this.fileName,
                filePath:this.filePath,
                size:this.filSize || 0
            }
        }
      },
      beforeUpdate(){
        
      },
      beforeDestroy() {
          this.cancelUpload()
          // window.removeEventListener('resize', this.setStyle)
      },
      methods: {
        handleImage(logo) {
              let src = ''
              if(logo) {
                  if(logo.indexOf('Learn') > -1) {
                      src = logo
                  } else {
                      src = `/Learn/${logo}`
                  }
              } else {
                  src = this.defaultImg
              }
              return src
          },
          removeFile() {
            this.uploadFile = {};
            this.$emit('input', {}); //v-model
            this.$emit('update:filePath', ''); //.sync
            this.$emit('update:fileName',''); 
            this.$emit('update:fileId', ''); 
            this.$emit('update:fileSize',0); 
          },
          // 上传图片成功后的回调函数，获取图片上传后的保存的位置，用于回显图片
          getFileUrl(res) {
              if (res.code == 1) {
                    let file = {
                        fileId: res.info.id,
                        filePath: res.data,
                        fileName: res.info.originalName,
                        size:res.info.size
                    }
                    this.$emit('input', file); //v-model
                    this.$emit('update:filePath', file.filePath); 
                    this.$emit('update:fileName', file.fileName); 
                    this.$emit('update:fileId', file.fileId); 
                    this.$emit('update:fileSize',file.size); 
                    this.$emit('upload-success', file); 
                    this.loading = false;
              } else {
                //   this.$Message.error('文件上传失败')
                  this.$Message.error(res.message)
                  this.uploadFile = {};
                  this.loading = false;
              }
          },
          getFileName (name) {
              return name.substring(0, name.lastIndexOf("."))
          },
          cancelUpload(){ //取消上传
              this.$refs.uploadFile.clearFiles()
              // this.source && this.source.cancel('cancelUpload'); //需要请求接口上传就放出来，手动ajax上传有效
              // this.source = '';
              this.removeFile();
              this.loading = false;
          },
          handleUploadIcon(file,a,b){
              this.speed = 0;
              this.loaded = 0;
              this.progress = 0;
              this.uploadFile = {};
              if (file) {
                let {name,size} = file;
                this.onlyFileName = name + '_' + new Date().getTime();
                this.size = this.getFileSize(size);
                //验证名称
                if(name){
                    let fileName = this.getFileName(name);
                    // let reg = new RegExp("^[\u4E00-\u9FA5a-zA-Z0-9_ -]*$");
                    let reg = new RegExp('/[\\/:*?"<>|]/gi');
                    if (reg.test(fileName) || fileName.length > 64) {
                        this.$Message.warning('文件名不能包含下列任意英文字符 \ / : * ? " < > |，长度为1-64个字符')
                        return false;
                    }
                }
                let fileSuffix = name.substring(name.lastIndexOf(".")+1).trim().toLowerCase();
                this.uploadAction = this.getUploadAction(fileSuffix);
                this.loading = true;
                let format = this.format;
                if(this.type && !this.$props.format){
                    format = this[`${this.type}Arr`]
                }
                if (format && format.length > 0) {
                    if(fileSuffix && format.indexOf(fileSuffix)>-1){
                        this.uploadFile = file;
                        this.uploadList = this.$refs.uploadFile.fileList; //用于显示进度
                        // 什么都不需要做
                    }else{
                        this.$Message.warning('不支持当前文件类型')
                        this.loading = false;
                        return false
                    }
                }
                return new Promise((resolve,reject) => { //组件自动上传
                    resolve(file)
                })
            }
          },
          getProgress(progressEvent,file, fileList) {
            console.log(progressEvent,file, fileList)
            if(progressEvent.percent){
                if(!file || !fileList || !fileList.find(item => item.uid === file.uid)){
                    return
                }
                this.progress = progressEvent.percent
            }else{
                var complete = Math.floor(progressEvent.loaded / progressEvent.total * 100)
                this.progress = complete
            }
            let aaspeed = Number(progressEvent.loaded - this.loaded) || 0
            this.loaded = progressEvent.loaded
            if(aaspeed > 1024 * 1024) {
                this.speed = Math.max((Math.round(aaspeed * 100 / (1024 * 1024)) / 100).toString(),0) + 'MB/s'
            } else {
                this.speed = Math.max((Math.round(aaspeed * 100 / 1024) / 100).toString(),0) + 'KB/s'
            }
            // this.loading = true;
        },
        getFileSize(size) {
            let fileSize;
            if(size > 1024 * 1024) {
                fileSize = (Math.round(size * 100 / (1024 * 1024)) / 100).toString() + 'MB'
            } else {
                fileSize = (Math.round(size * 100 / 1024) / 100).toString() + 'KB'
            }
            return fileSize;
        },
        getUploadAction(fileSuffix){
            let action = '',bucket = '',type = '';
            let uploadAction = `/api/minio/upload/permanent`
            type =  this.type || ['images','docs','videos','audios','glb','files'].find(type => this[`${type}Arr`].includes(fileSuffix)) || 'files';  
            this.fileType = fileSuffix === 'glb' ? 'glb' : type;
            bucket = this.bucket ? this.bucket : this.fileType === 'glb' ? 'relay' : type
            action = `${uploadAction}?visibility=company&bucket=${bucket}&type=${this.fileType}`
            return action
        },
        handleUpload(file,action){
            let formData = new window.FormData() //ajax手动上传
            formData.append('file', file);
            let curFile = {
                name:this.onlyFileName//this.formItem.file.name
            };
            let _this = this;
            const CancelToken = this.axios.CancelToken;
            this.source = CancelToken.source();
            this.axios({
                method:'post',
                url: action,
                data: formData,
                headers:{
                    'Content-type':'multipart/form-data',
                },
                cancelToken: this.source.token,
                timeout:0,
                onUploadProgress: (progressEvent) => {
                // console.log('到这里了吗')
                //解决点击手动上传过程中关闭了modal,再选择文件，会显示上次上传的进度级速度问题 
                if((curFile.name && _this.onlyFileName) && curFile.name != _this.onlyFileName){
                    return;
                };
                _this.getProgress(progressEvent,file)
                }
            }).then(res=>{
                if(res.data.code == 1){
                    this.getFileUrl(res.data)
                }else {
                    this.$Message.warning('上传文件失败')
                }
                clearInterval(this.uplaodInterval)
                this.loading = false;
                this.uploadFile = {};
            }).catch((error) => {
                this.loading = false;
                this.uploadFile = {};
                if(error.message !== 'cancelUpload'){
                    this.$Message.error('文件上传异常')
                }
                clearInterval(this.uplaodInterval)
            })
          },
      }
  }
  </script>
  
  <style scoped>
  .choose-btn {
      float: left;
      margin: 1px 6px 0 0;
  }
  
  .file-list {
      max-height: 132px;
      overflow: auto;
      width: 100%;
      display: flex;
      align-items: center;
      margin: 6px;
      justify-content: space-between;
      background: var(--table-tr-hover-color);
  }
  .file-list .file-name {
      flex: 1;
      margin-left: 6px;
  }
  
  .file-list /deep/ button {
      border: none !important;
  }
  
  .file-list /deep/ button i {
      font-size: 16px;
      color: #ed4014;
  }
  .mr5{
      margin-right:5px;
  }
  .mw30{
      max-width: calc(33% - 5px);
  }
  .flex{
      display: flex;
  }
  </style>